
COMMON A,R,O VARIABLES IN HOJJAT DATA FILE AT THREE TIME POINTS LINKING THESE THREE VARIABLES WITH THE SAME FACTOR LOADINGS AT EACH OF THE THREE TIME POINTS. POSITIVE DEFINITE COVARIANCE MATRIX SO NOT SUITABLE FOR A THREE FACTOR MODEL.

ETA1   ETA2   ETA3

# simpler latent change score model with fewer constraints; has data in excel available
https://quantdev.ssri.psu.edu/sites/qdev/files/GMCh14_Common_Factor.html

#set filepath
A <- read.spss("U:\\My Documents\\A.sav")
A <- data.frame(A)
head(A)

config.invar<-'#factor loadings
               eta1 =~ lambda_S*A1+
                       lambda_R3*R1+ 
                       lambda_M3*O1
               eta2 =~ lambda_S*A2+
                       lambda_R5*R2+ 
                       lambda_M5*O2
               eta3 =~ lambda_S*A3+
                       lambda_R8*R3+ 
                       lambda_M8*O3
              #latent variable variances
                      eta1~~1*eta1
                      eta2~~eta2
                      eta3~~eta3
              #latent variable covariances
                      eta1~~eta2
                      eta1~~eta3
                      eta2~~eta3
              #unique variances
                      A1~~A1
                      A2~~A2
                      A3~~A3
                      R1~~R1
                      R2~~R2
                      R3~~R3
                      O1~~O1
                      O2~~O2
                      O3~~O3
              #unique covariances
                      A1~~A2
                      A1~~A3
                      A2~~A3
                      R1~~R2
                      R1~~R3
                      R2~~R3
                      O1~~O2
                      O1~~O3
                      O2~~O3
              #latent variable intercepts
                      eta1~0*1
                      eta2~1
                      eta3~1
              #observed variable intercepts
                      A1~tau_S*1
                      A2~tau_S*1
                      A3~tau_S*1
                      R1~tau_R3*1
                      R2~tau_R5*1
                      R3~tau_R8*1
                      O1~tau_M3*1
                      O2~tau_M5*1
                      O3~tau_M8*1'
lavaan.fit1<-lavaan(config.invar,
                data = A,
                meanstructure = TRUE,
                estimator = "ML",
                missing = "fiml",
                                     fixed.x = FALSE)
summary(lavaan.fit1, fit.measures=TRUE)

ec <- data.frame(eclsk)
mean(ec[,2],na=T)
mean(ec[,3],na=T)
mean(ec[,4],na=T)
mean(ec[,5],na=T)
mean(ec[,6],na=T)
mean(ec[,7],na=T)
mean(ec[,8],na=T)
mean(ec[,9],na=T)
mean(ec[,10],na=T)

>>>>>>>>>>>>>>>>>>>

Different ability score means but same factor means and covariance structure between the ability scores over time

weak.invar<-'#factor loadings (with constraints)
               eta1 =~ lambda_S*s_g3+
                       lambda_R*r_g3+ 
                       lambda_M*m_g3
               eta2 =~ lambda_S*s_g5+
                       lambda_R*r_g5+ 
                       lambda_M*m_g5
               eta3 =~ lambda_S*s_g8+
                       lambda_R*r_g8+ 
                       lambda_M*m_g8
                #latent variable variances
                        eta1~~1*eta1
                        eta2~~eta2
                        eta3~~eta3
                #latent variable covariances
                        eta1~~eta2
                        eta1~~eta3
                        eta2~~eta3
                #unique variances
                        s_g3~~s_g3
                        s_g5~~s_g5
                        s_g8~~s_g8
                        r_g3~~r_g3
                        r_g5~~r_g5
                        r_g8~~r_g8
                        m_g3~~m_g3
                        m_g5~~m_g5
                        m_g8~~m_g8
                #unique covariances
                        s_g3~~s_g5
                        s_g3~~s_g8
                        s_g5~~s_g8
                        r_g3~~r_g5
                        r_g3~~r_g8
                        r_g5~~r_g8
                        m_g3~~m_g5
                        m_g3~~m_g8
                        m_g5~~m_g8
                #latent variable intercepts
                        eta1~0*1
                        eta2~1
                        eta3~1
                #observed variable intercepts
                        s_g3~tau_S*1
                        s_g5~tau_S*1
                        s_g8~tau_S*1
                        r_g3~tau_R3*1
                        r_g5~tau_R5*1
                        r_g8~tau_R8*1
                        m_g3~tau_M3*1
                        m_g5~tau_M5*1
                        m_g8~tau_M8*1'
lavaan.fit2<-lavaan(weak.invar,
                data = eclsk,
                meanstructure = TRUE,
                estimator = "ML",
                missing = "fiml",
                fixed.x = FALSE)
summary(lavaan.fit2, fit.measures=TRUE)

# strong invariance
# equal means and covariances over time

strong.invar<-'#factor loadings (with constraints)
               eta1 =~ lambda_S*s_g3+
                       lambda_R*r_g3+ 
                       lambda_M*m_g3
               eta2 =~ lambda_S*s_g5+
                       lambda_R*r_g5+ 
                       lambda_M*m_g5
               eta3 =~ lambda_S*s_g8+
                       lambda_R*r_g8+ 
                       lambda_M*m_g8
              #latent variable variances
                      eta1~~1*eta1
                      eta2~~eta2
                      eta3~~eta3
              #latent variable covariances
                      eta1~~eta2
                      eta1~~eta3
                      eta2~~eta3
              #unique variances
                      s_g3~~s_g3
                      s_g5~~s_g5
                      s_g8~~s_g8
                      r_g3~~r_g3
                      r_g5~~r_g5
                      r_g8~~r_g8
                      m_g3~~m_g3
                      m_g5~~m_g5
                      m_g8~~m_g8
              #unique covariances
                      s_g3~~s_g5
                      s_g3~~s_g8
                      s_g5~~s_g8
                      r_g3~~r_g5
                      r_g3~~r_g8
                      r_g5~~r_g8
                      m_g3~~m_g5
                      m_g3~~m_g8
                      m_g5~~m_g8
              #latent variable intercepts
                      eta1~0*1
                      eta2~1
                      eta3~1
              #observed variable intercepts (with constraints)
                      s_g3~tau_S*1
                      s_g5~tau_S*1
                      s_g8~tau_S*1
                      r_g3~tau_R*1
                      r_g5~tau_R*1
                      r_g8~tau_R*1
                      m_g3~tau_M*1
                      m_g5~tau_M*1
                      m_g8~tau_M*1'
lavaan.fit3<-lavaan(strong.invar,
                data = eclsk,
                meanstructure = TRUE,
                estimator = "ML",
                missing = "fiml",
                fixed.x = FALSE)
summary(lavaan.fit3, fit.measures=TRUE)

>>>>>>>>>>>>>>>>>

# has diagram of model on longitudinal maths data
https://longitudinalresearchinstitute.com/tutorials/chapter-16-latent-change-score-modeling/
# has no diagram but uses same maths data over tine
https://quantdev.ssri.psu.edu/sites/qdev/files/GM_Chp17_tutorial.html

dcm_math <- ' #opening quote
#MATHEMATICS
  #latent true scores (loadings = 1)
    lm1 =~ 1*math2
    lm2 =~ 1*math3
    lm3 =~ 1*math4
    lm4 =~ 1*math5
    lm5 =~ 1*math6
    lm6 =~ 1*math7
    lm7 =~ 1*math8

  #latent true score means (initial free, others = 0)  
    lm1 ~ 1
    lm2 ~ 0*1
    lm3 ~ 0*1
    lm4 ~ 0*1
    lm5 ~ 0*1
    lm6 ~ 0*1
    lm7 ~ 0*1

  #latent true score variances (initial free, others = 0)
    lm1 ~~ start(15)*lm1
    lm2 ~~ 0*lm2
    lm3 ~~ 0*lm3
    lm4 ~~ 0*lm4
    lm5 ~~ 0*lm5
    lm6 ~~ 0*lm6
    lm7 ~~ 0*lm7

  #observed intercepts (fixed to 0)
    math2 ~ 0*1
    math3 ~ 0*1
    math4 ~ 0*1
    math5 ~ 0*1
    math6 ~ 0*1
    math7 ~ 0*1
    math8 ~ 0*1

  #observed residual variances (constrained to equality)
    math2 ~~ sigma2_u*math2
    math3 ~~ sigma2_u*math3
    math4 ~~ sigma2_u*math4
    math5 ~~ sigma2_u*math5
    math6 ~~ sigma2_u*math6
    math7 ~~ sigma2_u*math7
    math8 ~~ sigma2_u*math8

  #autoregressions (fixed = 1)
    lm2 ~ 1*lm1
    lm3 ~ 1*lm2
    lm4 ~ 1*lm3
    lm5 ~ 1*lm4
    lm6 ~ 1*lm5
    lm7 ~ 1*lm6

  #latent change scores (fixed = 1)
    dm2 =~ 1*lm2
    dm3 =~ 1*lm3
    dm4 =~ 1*lm4
    dm5 =~ 1*lm5
    dm6 =~ 1*lm6
    dm7 =~ 1*lm7

  #latent change score means (constrained to 0)  
    dm2 ~ 0*1
    dm3 ~ 0*1
    dm4 ~ 0*1
    dm5 ~ 0*1
    dm6 ~ 0*1
    dm7 ~ 0*1

  #latent change score variances (constrained to 0)  
    dm2 ~~ 0*dm2
    dm3 ~~ 0*dm3
    dm4 ~~ 0*dm4
    dm5 ~~ 0*dm5
    dm6 ~~ 0*dm6
    dm7 ~~ 0*dm7

  #constant change factor (loadings = 1)
    g2 =~ 1*dm2 + 
          1*dm3 + 
          1*dm4 + 
          1*dm5 + 
          1*dm6 + 
          1*dm7 

  #constant change factor mean  
    g2 ~ start(15)*1

  #constant change factor variance
    g2 ~~ g2

  #constant change factor covariance with the initial true score
    g2 ~~ lm1

  #proportional effects (constrained equal)
    dm2 ~ start(-.2)*pi_m * lm1
    dm3 ~ start(-.2)*pi_m * lm2
    dm4 ~ start(-.2)*pi_m * lm3
    dm5 ~ start(-.2)*pi_m * lm4
    dm6 ~ start(-.2)*pi_m * lm5
    dm7 ~ start(-.2)*pi_m * lm6
' #closing quote
2.2 Model Estimation and Interpretation
We fit the model using lavaan.

#Model fitting
fit_math <- lavaan(dcm_math,
                data = nlsy_data, #note that fitting uses wide data
                meanstructure = TRUE,
                estimator = "ML",
                missing = "fiml",
                fixed.x = FALSE,
                mimic="mplus",
                control=list(iter.max=500),
                verbose=FALSE)